package controllers

import java.io.File

import javax.inject.Inject
import play.api.mvc.{AbstractController, ControllerComponents}
import tool._
import dao._
import models.Tables._
import org.joda.time.DateTime
import play.api.libs.json.Json
import utils.Utils

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import utils.Implicits._

import scala.collection.mutable
import implicits.Implicits._


/**
 * Created by Administrator on 2019/8/7
 */
class AdminController @Inject()(cc: ControllerComponents, formTool: FormTool, accountDao: AccountDao,
                                keggInfoDao: KeggInfoDao,
                                userDao: UserDao, tool: Tool)(implicit val modeDao: ModeDao) extends
  AbstractController(cc) {

  def userManageBefore = Action { implicit request =>
    Ok(views.html.admin.userManage())
  }

  def logout = Action { implicit request =>
    Redirect(routes.AppController.loginBefore()).flashing("info" -> "退出登录成功!").removingFromSession("admin")
  }

  def changePasswordBefore = Action { implicit request =>
    Ok(views.html.admin.changePassword())
  }

  def changePassword = Action.async { implicit request =>
    val data = formTool.changePasswordForm.bindFromRequest().get
    accountDao.selectById1.flatMap { x =>
      if (data.password == x.password) {
        val row = AccountRow(x.id, x.account, data.newPassword)
        accountDao.update(row).map { y =>
          Redirect(routes.AppController.loginBefore()).flashing("info" -> "密码修改成功!").removingFromSession("admin")
        }
      } else {
        Future.successful(Redirect(routes.AdminController.changePasswordBefore()).flashing("info" -> "用户名或密码错误!"))
      }
    }
  }

  def getAllUser = Action.async { implicit request =>
    getAllUserAction
  }

  def getAllUserAction = {
    userDao.selectAll.map { x =>
      val array = Utils.getArrayByTs(x)
      Ok(Json.toJson(array))
    }
  }

  def deleteUserById = Action.async { implicit request =>
    val data = FormTool.idForm.bindFromRequest().get
    userDao.deleteById(data.id).flatMap { x =>
      Future {
        val userIdDir = Tool.getUserIdDir(data.id)
        Utils.deleteDirectory(userIdDir)
      }
      getAllUserAction
    }
  }

  def addUser = Action.async { implicit request =>
    val data = formTool.userForm.bindFromRequest().get
    val row = UserRow(0, data.name, data.password, data.unit, new DateTime())
    userDao.insert(row).flatMap { x =>
      getAllUserAction
    }
  }

  def getUserById = Action.async { implicit request =>
    val data = FormTool.idForm.bindFromRequest().get
    userDao.selectById(data.id).map { x =>
      Ok(Utils.getJsonByT(x))
    }
  }

  def updateUser = Action.async { implicit request =>
    val data = formTool.userForm.bindFromRequest().get
    userDao.selectByNameSome(data.name).flatMap { dbUser =>
      val row = dbUser.copy(password = data.password, unit = data.unit)
      userDao.update(row).flatMap { x =>
        getAllUserAction
      }

    }

  }

  def userNameCheck = Action.async { implicit request =>
    val data = formTool.userNameForm.bindFromRequest.get
    userDao.selectByName(data.name).zip(accountDao.selectById1).map { case (optionUser, admin) =>
      optionUser match {
        case Some(y) => Ok(Json.obj("valid" -> false))
        case None =>
          val valid = if (data.name == admin.account) false else true
          Ok(Json.obj("valid" -> valid))
      }
    }
  }

  def metaboDbManageBefore = Action { implicit request =>
    Ok(views.html.admin.metaboDbManage())
  }

  def getAllMetaboDb = Action.async { implicit request =>
    keggInfoDao.selectAll.map { keggInfos =>
        val sortRows = if (keggInfos.forall(x => x.index.isInt)) {
          keggInfos.sortBy(_.index.toInt)
        } else keggInfos
        val array = Utils.getArrayByTs(sortRows)
        val columnNames = List("index", "name", "strandardName", "superclass", "accession", "keggid")
        val json = Json.obj("columnNames" -> columnNames, "array" -> array)
        Ok(json)
      }
  }

  def updateMetaboDb = Action.async(parse.multipartFormData) { request =>
    val file = request.body.file("file").get
    val tmpDir = Tool.createTempDirectory("tmpDir")
    val tmpFile = new File(tmpDir, "tmp.xlsx")
    file.ref.moveTo(tmpFile, true)
    val myMessage = FileTool.metaboFileCheck(tmpFile)
    if (!myMessage.valid) {
      Tool.deleteDirectory(tmpDir)
      Future.successful(Ok(Json.obj("error" -> myMessage.message)))
    } else {
      val lines = tmpFile.xlsxLines
      val headers = lines.head
      val keggInfos = lines.drop(1).mapOtherByColumns { columns =>
        val lineMap = headers.zip(columns).toMap
        val name = lineMap("Name")
        val strandardName = lineMap("Standard.name")
        KegginfoRow(lineMap("Index"), name, strandardName, lineMap.getOrElse("HMDBID", "NA"),
          lineMap.getOrElse("KeggID", "NA"), lineMap("Class"))
      }
      keggInfoDao.updates(keggInfos).map { x =>
        Tool.deleteDirectory(tmpDir)
        Ok(Json.toJson("success!"))
      }
    }
  }


}
